package business

import (
	"fcs-api/src/app/model"
	"fcs-api/src/app/service/bss"
	"fmt"
	"strconv"
	"time"

	"github.com/google/uuid"
)

func ReportDaily() error {
	billInvoke := &model.BillInvoke{
		Id: uuid.New().String(),
	}
	_, err := model.CreateBillInvoke(billInvoke)
	if err != nil {
		_ = logger.Error("ReportDaily: insert bill invoke error, %s", err.Error())
	}
	billList, err := getPayBillList()
	if err != nil {
		return err
	}
	if len(billList) != 0 {
		orderMap, err := getOrderMap()
		if err != nil {
			return err
		}
		bssOrderList := getBssBillList(billList, orderMap)
		bss.SendBill(bssOrderList)
	}
	return nil
}

func getOrderMap() (map[string]*model.Order, error) {
	orderList, err := model.GetAllOrder()
	if err != nil {
		_ = logger.Error("getOrderMap: get order list error, %s", err.Error())
		return nil, err
	}
	orderMap := make(map[string]*model.Order)
	for _, order := range orderList {
		orderMap[order.AccountId] = order
	}
	return orderMap, nil
}

func getBssBillList(billList []*model.BillInfo, orderMap map[string]*model.Order) []*bss.BssOrder {
	dateStr := time.Now().AddDate(0, 0, -1).Format("20060102")
	bssOrderList := make([]*bss.BssOrder, 0)
	for i, bill := range billList {
		if order, ok := orderMap[bill.UserId]; ok {
			bssOrder := new(bss.BssOrder)
			bssOrder.UserId = bill.UserId
			bssOrder.Index = int64(i)
			bssOrder.Subpackage = false
			bssOrder.PackageCount = 1
			bssOrder.PackageNo = 1
			bssOrder.SettleCycle = "DAY"
			bssOrder.BillCycle = dateStr
			bssOrder.ProductLineCode = "FCS"
			bssOrder.HaveOtherItem = false
			bssOrder.BillType = "dailyNetflow"

			count := bss.Item{
				Code:  "call_times",
				Value: strconv.FormatInt(bill.Count, 10),
			}
			computePower := bss.Item{
				Code:  "resource_usage",
				Value: fmt.Sprintf("%.6f", bill.Compute),
			}
			egressTraffic := bss.Item{
				Code:  "egress_traffic",
				Value: "0",
			}
			bssOrder.ProductList = []*bss.BillProduct{
				{
					Region:          model.Base.Region,
					AvailableZone:   "",
					ProductTypeCode: "FCS",
					InstanceId:      order.InstanceId,
					InstanceName:    "",
					ItemList:        []*bss.Item{&count, &computePower, &egressTraffic},
				}}
			bssOrderList = append(bssOrderList, bssOrder)
		}
	}
	sum := int64(len(bssOrderList))
	for _, order := range bssOrderList {
		order.Count = sum
	}
	return bssOrderList
}

func getPayBillList() ([]*model.BillInfo, error) {
	startBillList, err := getMonthStartBill()
	if err != nil {
		_ = logger.Error("ReportDaily: get start bill list error, %s", err.Error())
		return nil, err
	}
	dayBeforeBillList, err := getMonthStartToDayBeforeBill()
	if err != nil {
		_ = logger.Error("ReportDaily: get day before bill list error, %s", err.Error())
		return nil, err
	}
	dayBeforeBillMap := transBillListToMap(dayBeforeBillList)
	payBillList := make([]*model.BillInfo, 0)
	// 计算出超出免费额度的部分
	for _, startBill := range startBillList {
		var lastHourCount int64 = 0
		var lastHourComputePower float64 = 0
		if dayBeforeBill, ok := dayBeforeBillMap[startBill.UserId]; ok {
			lastHourCount = startBill.Count - dayBeforeBill.Count
			lastHourComputePower = startBill.Compute - dayBeforeBill.Compute
		} else {
			lastHourCount = startBill.Count
			lastHourComputePower = startBill.Compute
		}

		if startBill.Count > model.Base.FreeCount || startBill.Compute > model.Base.FreeComputePower {
			payBill := new(model.BillInfo)
			payBill.UserId = startBill.UserId
			if startBill.Count > model.Base.FreeCount {
				exceedCount := startBill.Count - model.Base.FreeCount
				// 取两个中最小的
				if exceedCount > lastHourCount {
					payBill.Count = lastHourCount
				} else {
					payBill.Count = exceedCount
				}
			}
			if startBill.Compute > model.Base.FreeComputePower {
				exceedCompute := startBill.Compute - model.Base.FreeComputePower
				// 取两个中最小的
				if exceedCompute > lastHourComputePower {
					payBill.Compute = lastHourComputePower
				} else {
					payBill.Compute = exceedCompute
				}
			}
			if payBill.Count > 0 || payBill.Compute > 0 {
				payBillList = append(payBillList, payBill)
			}
		}
	}
	return payBillList, nil
}

// 获取从月初开始到前一天的数据
func getMonthStartBill() ([]*model.BillInfo, error) {
	yesterday := time.Now().AddDate(0, 0, -1)
	yesterdayStart := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, yesterday.Location())
	yesterdayEnd := yesterdayStart.AddDate(0, 0, 1)
	monthStart := time.Date(yesterday.Year(), yesterday.Month(), 1, 0, 0, 0, 0, yesterday.Location())
	return model.GetBillInfo(monthStart.Unix(), yesterdayEnd.Unix())
}

// 获取从月初开始到前两天的数据
func getMonthStartToDayBeforeBill() ([]*model.BillInfo, error) {
	yesterday := time.Now().AddDate(0, 0, -1)
	// 如果前一天就是每个月的1号，那么返回空数组
	if yesterday.Day() == 1 {
		return make([]*model.BillInfo, 0), nil
	}
	yesterdayStart := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, yesterday.Location())
	monthStart := time.Date(yesterday.Year(), yesterday.Month(), 1, 0, 0, 0, 0, yesterday.Location())
	return model.GetBillInfo(monthStart.Unix(), yesterdayStart.Unix())
}

func transBillListToMap(billList []*model.BillInfo) map[string]*model.BillInfo {
	billMap := make(map[string]*model.BillInfo)
	for _, bill := range billList {
		billMap[bill.UserId] = bill
	}
	return billMap
}
